﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Xml.Linq;
using OvenParameterForm.UserInterface;

namespace OvenParameterForm.Util
{
    internal class PublicFunc
    {
        /// <summary>
        /// 递归刷新控件
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="list"></param>
        public static void UpdateDataAddList(Control obj, List<IUpdateData> list)
        {
            foreach (Control control in obj.Controls)
            {
                if (control is IUpdateData) list.Add((IUpdateData)control);
                UpdateDataAddList(control, list);
            }
        }
        /// <summary>
        /// 获取某个实例的属性和属性值并转化为XElement元素和属性
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="t">实例类</param>
        /// <returns></returns>
        internal static XElement ClassToXML<T>(T t, bool isField = false)
        {
            XElement xo = new XElement(t.GetType().Name);
            List<XAttribute> xa = new List<XAttribute>();
            if (isField)
            {
                List<FieldInfo> hehe0 = t.GetType().GetFields().ToList();

                hehe0.ForEach(f =>
                {
                    XAttribute x = new XAttribute(f.Name, f.GetValue(t)?.ToString() ?? "");
                    xa.Add(x);
                });
            }
            else
            {
                IEnumerable<PropertyInfo> hehe = t.GetType().GetRuntimeProperties();
                foreach (PropertyInfo pi in hehe)
                {
                    XAttribute x = new XAttribute(pi.Name, pi.GetValue(t)?.ToString() ?? "");
                    xa.Add(x);
                }
            }
            xo.Add(xa.ToArray());
            return xo;
        }

        /// <summary>
        /// XElement信息填充到指定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xo"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        internal static T XMLToClass<T>(XElement xo, T t, bool isField = false)
        {
            List<XAttribute> xa = xo.Attributes().ToList();
            xa.ForEach(a =>
            {
                string propertyName = a.Name.ToString();
                if (isField)
                {
                    FieldInfo fi = t.GetType().GetField(propertyName);
                    object o = Convert.ChangeType(a.Value, fi.FieldType);
                    t.GetType().GetField(propertyName).SetValue(t, o);
                }
                else
                {
                    PropertyInfo pi = t.GetType().GetProperty(propertyName);
                    object o = Convert.ChangeType(a.Value, pi.PropertyType);
                    t.GetType().GetProperty(propertyName).SetValue(t, o, null);
                }
            });
            return t;
        }
        internal static int BoolArrayGetValue(bool[] item)
        {
            int result = 0;
            for (int i = 0; i < item.Length; i++)
            {
                result = (result << 1) + (item[i] ? 1 : 0);
            }
            return result;
        }
        /// <summary>
        /// 递归方法将控件中符合条件的子空间放入子控件集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="tlist"></param>
        internal static void Addlist<T>(Control obj, List<T> tlist) where T : Control
        {
            foreach (Control item in obj.Controls)
            {
                if (item is T)
                    tlist.Add((T)item);
                Addlist(item, tlist);
            }
        }
        /// <summary>
        /// 将控件中的某种子控件的值转化为相应类
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">母控件</param>
        /// <param name="s">子控件</param>
        /// <param name="t">类型</param>
        internal static void ControlToClass<S, T>(Control obj, S s, T t) where S : Control
        {
            IEnumerable<PropertyInfo> pi = t.GetType().GetRuntimeProperties();
            List<S> txtControl = new List<S>();
           Addlist(obj, txtControl);
            var temp = from p in pi
                       join t0 in txtControl on p.Name equals t0.Name.Split('_')[1]
                       select new { propername = p.Name, propervalue = Convert.ChangeType(t0.Text, p.PropertyType) };
            temp.ToList().ForEach(x =>
            t.GetType().GetProperty(x.propername).SetValue(t, x.propervalue, null));
        }
        internal static void ClassToControl<S, T>(Control obj, S s, T t) where S : Control
        {
            IEnumerable<PropertyInfo> pi = t.GetType().GetRuntimeProperties();
            List<S> txtControl = new List<S>();
            Addlist(obj, txtControl);
            txtControl.ForEach(x =>
            {
                var b = pi.FirstOrDefault(p => p.Name == x.Name.Split('_')[1]);
                if (b != null) { x.Text = b.GetValue(t, null).ToString(); }
            });
        }
    }
}
